#include <glib.h>
#include "GEventWrapper.h"

CGEventWrapper::CGEventWrapper()
:m_created(FALSE)
,m_manualReset(FALSE)
,m_initialState(FALSE)
#if GLIB_CHECK_VERSION(2, 32, 0)
#else
,m_access(NULL)
,m_sig(NULL)
#endif
,m_flag(FALSE)
{

}

CGEventWrapper::CGEventWrapper(gboolean manualReset, gboolean initialState)
:m_created(FALSE)
#if GLIB_CHECK_VERSION(2, 32, 0)
#else
,m_access(NULL)
,m_sig(NULL)
#endif
,m_flag(FALSE)
{
  Create(manualReset, initialState);
}

gboolean CGEventWrapper::Create(gboolean manualReset, gboolean initialState)
{
  g_return_val_if_fail(!m_created, FALSE);

  m_manualReset = manualReset;
  m_initialState = initialState;
#if GLIB_CHECK_VERSION(2, 32, 0)
  g_mutex_init(&m_access);
  g_cond_init(&m_sig);
#else
  m_access = g_mutex_new();
  m_sig = g_cond_new();
#endif
  m_flag = FALSE;
  m_created = TRUE;

  /* initial state */
  if(m_initialState)
    Set();

  return m_created;
}

gboolean CGEventWrapper::Destroy()
{
  /* already destroyed or not created */
  if(!m_created)
    return FALSE;

#if GLIB_CHECK_VERSION(2, 32, 0)
  g_mutex_clear(&m_access);

  g_cond_clear(&m_sig);
#else
  g_mutex_free(m_access);
  m_access = NULL;

  g_cond_free(m_sig);
  m_sig = NULL;
#endif

  m_created = FALSE;

  return !m_created;
}

CGEventWrapper::~CGEventWrapper()
{
  Destroy();
}

gboolean CGEventWrapper::Set()
{
#if GLIB_CHECK_VERSION(2, 32, 0)
  g_mutex_lock(&m_access);
#else
  g_mutex_lock(m_access);
#endif
  
  m_flag = TRUE;
#if GLIB_CHECK_VERSION(2, 32, 0)
  g_cond_broadcast(&m_sig);
#else
  g_cond_broadcast(m_sig);
#endif

#if GLIB_CHECK_VERSION(2, 32, 0)
  g_mutex_unlock(&m_access);
#else
  g_mutex_unlock(m_access);
#endif

  return TRUE;
}

gboolean CGEventWrapper::Wait(gulong milis)
{
#if GLIB_CHECK_VERSION(2, 32, 0)
  g_mutex_lock(&m_access);
#else
  g_mutex_lock(m_access);
#endif

  gboolean ret = TRUE;
  while(!m_flag)
  {
    if(milis == WAIT_INFINITE)
#if GLIB_CHECK_VERSION(2, 32, 0)
	  g_cond_wait(&m_sig, &m_access);
#else
	  g_cond_wait(m_sig, m_access);
#endif
	else
    {
#if GLIB_CHECK_VERSION(2, 32, 0)
	  gint64 endTime = milis;
	  if(!g_cond_wait_until(&m_sig, &m_access, endTime))
#else
	  GTimeVal absTime;
      g_get_current_time(&absTime);
      g_time_val_add(&absTime, milis * 1000 /*microseconds*/);
      if(!g_cond_timed_wait(m_sig, m_access, &absTime))
#endif
        break;
      ret = m_flag;
    }
  }

#if GLIB_CHECK_VERSION(2, 32, 0)
  g_mutex_unlock(&m_access);
#else
  g_mutex_unlock(m_access);
#endif

  /* cleaar case auto reset */
  if(ret && !m_manualReset)
    Clear();

  return ret;
}

gboolean CGEventWrapper::IsSet()
{
  gboolean ret = FALSE;

#if GLIB_CHECK_VERSION(2, 32, 0)
  g_mutex_lock(&m_access);
#else
  g_mutex_lock(m_access);
#endif  

  ret = m_flag;

#if GLIB_CHECK_VERSION(2, 32, 0)
  g_mutex_unlock(&m_access);
#else
  g_mutex_unlock(m_access);
#endif

  return ret;
}

gboolean CGEventWrapper::Clear()
{
#if GLIB_CHECK_VERSION(2, 32, 0)
  g_mutex_lock(&m_access);
#else
  g_mutex_lock(m_access);
#endif  
  
  m_flag = FALSE;

#if GLIB_CHECK_VERSION(2, 32, 0)
  g_mutex_unlock(&m_access);
#else
  g_mutex_unlock(m_access);
#endif  

  return TRUE;
}
